﻿using BlogDemo.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace BlogDemo.Data
{
    /// <summary>
    /// 实体仓储规范
    /// </summary>
    /// <typeparam name="T">实体对象</typeparam>
    public interface IRepository<T, TKey> : IRepository<T> where T : class, IEntity, IEntity<TKey> where TKey : IComparable<TKey>
    {
        T Find(TKey Id);
    }

    public interface IRepository<T> : IDisposable where T : class, IEntity
    {
        /// <summary>
        /// Gets a table record
        /// </summary>
        IQueryable<T> Table { get; }
        /// <summary>
        /// Gets a table with "no tracking" enabled (EF feature) Use it only when you load record(s) only for read-only operations
        /// </summary>
        IQueryable<T> TableNoTracking { get; }

        /// <summary>
        /// 获取指定标识的实体
        /// </summary>
        T Find(params object[] Id);
        /// <summary>
        /// 获取指定标识的实体
        /// </summary>
        T Find(Expression<Func<T, bool>> predicate);
        /// <summary>
        /// 查找符合特定表达式列表
        /// </summary>
        /// <param name="predicate">特定表达式</param>
        /// <param name="noTracking">是否需要跟踪Entity的属性状态</param>
        /// <returns></returns>
        IEnumerable<T> Query(Expression<Func<T, bool>> predicate = null);
        /// <summary>
        /// 查找符合特定表达式列表
        /// </summary>
        /// <typeparam name="TResult">新类型</typeparam>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <param name="selector">筛选的字段表达式</param>
        /// <returns></returns>
        IEnumerable<TResult> Query<TResult>(Expression<Func<T, bool>> predicate, Expression<Func<T, TResult>> selector);
        /// <summary>
        /// 查找符合特定表达式的数量
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns></returns>
        long Count(Expression<Func<T, bool>> predicate = null);
        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns></returns>
        bool Any(Expression<Func<T, bool>> predicate = null);
        // <summary>
        /// 添加实体.
        /// </summary>
        void Add(T entity);
        // <summary>
        /// 修改实体.
        /// </summary>
        void Update(T entity);
        // <summary>
        /// 移除实体.
        /// </summary>
        void Remove(T entity);

        #region Async

        /// <summary>
        /// 获取计数
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns></returns>
        Task<long> CountAsync(Expression<Func<T, bool>> predicate = null);
        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns></returns>
        Task<bool> AnyAsync(Expression<Func<T, bool>> predicate = null);
        /// <summary>
        /// 获取指定标识的实体
        /// </summary>
        Task<T> FindAsync(params object[] Id);
        /// <summary>
        /// 获取指定标识的实体
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns>一个实体</returns>
        Task<T> FindAsync(Expression<Func<T, bool>> predicate);
        /// <summary>
        /// 查找符合特定表达式列表
        /// </summary>
        /// <param name="predicate">特定表达式</param>
        /// <param name="noTracking">是否需要跟踪Entity的属性状态</param>
        /// <returns></returns>
        Task<IEnumerable<T>> QueryAsync(Expression<Func<T, bool>> predicate = null);
        /// <summary>
        /// 查找符合特定表达式<see cref="TResult"/>列表
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <param name="selectExpr">筛选的字段表达式</param>
        /// <returns></returns>
        Task<IEnumerable<TResult>> QueryAsync<TResult>(Expression<Func<T, bool>> predicate, Expression<Func<T, TResult>> selector);

        // <summary>
        /// 添加实体.
        /// </summary>
        Task AddAsync(T entity);
        // <summary>
        /// 修改实体.
        /// </summary>
        Task UpdateAsync(T entity);
        // <summary>
        /// 移除实体.
        /// </summary>
        Task RemoveAsync(T entity);
        #endregion

    }
}
